package org.eiahe.hr.attendance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.system.domain.SysMenu;
import org.eiahe.hr.attendance.domain.MonthlyOvertimeStat;
import org.eiahe.hr.attendance.domain.OvertimeRecord;
import org.eiahe.hr.attendance.domain.bo.MonthlyOvertimeStatBo;
import org.eiahe.hr.attendance.domain.vo.MonthlyOvertimeStatVo;
import org.eiahe.hr.attendance.mapper.MonthlyOvertimeStatMapper;
import org.eiahe.hr.attendance.mapper.OvertimeRecordMapper;
import org.eiahe.hr.attendance.service.IMonthlyOvertimeStatService;
import org.ehe.system.domain.HrEmployee;
import org.ehe.system.mapper.HrEmployeeMapper;
import org.eiahe.hr.filler.EmployeeNameFiller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.YearMonth;
import java.util.List;
import java.util.Objects;

/**
 * 月度加班统计Service业务层处理
 *
 * @author zhangnn
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class MonthlyOvertimeStatServiceImpl implements IMonthlyOvertimeStatService {

    private final MonthlyOvertimeStatMapper baseMapper;
    private final OvertimeRecordMapper overtimeRecordMapper;
    private final HrEmployeeMapper employeeMapper;
    private final EmployeeNameFiller employeeNameFiller;


    @Override
    public TableDataInfo<MonthlyOvertimeStatVo> queryPageList(MonthlyOvertimeStatBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<MonthlyOvertimeStat> lqw = buildQueryWrapper(bo);
        Page<MonthlyOvertimeStatVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        // 填充员工姓名和计算小时数
        result.getRecords().forEach(this::fillEmployeeInfoAndCalculateHours);

        return TableDataInfo.build(result);
    }

    @Override
    public List<MonthlyOvertimeStatVo> queryList(MonthlyOvertimeStatBo bo) {
        LambdaQueryWrapper<MonthlyOvertimeStat> lqw = buildQueryWrapper(bo);
        List<MonthlyOvertimeStatVo> list = baseMapper.selectVoList(lqw);

        // 填充员工姓名和计算小时数
        list.forEach(this::fillEmployeeInfoAndCalculateHours);

        return list;
    }

    private LambdaQueryWrapper<MonthlyOvertimeStat> buildQueryWrapper(MonthlyOvertimeStatBo bo) {
        LambdaQueryWrapper<MonthlyOvertimeStat> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getYear() != null, MonthlyOvertimeStat::getYear, bo.getYear());
        lqw.eq(bo.getMonth() != null, MonthlyOvertimeStat::getMonth, bo.getMonth());
        lqw.eq(StringUtils.isNotBlank(bo.getEmployeeNo()), MonthlyOvertimeStat::getEmployeeNo, bo.getEmployeeNo());
        lqw.eq(bo.getUserId() != null, MonthlyOvertimeStat::getUserId, bo.getUserId());
        lqw.orderByDesc(MonthlyOvertimeStat::getYear);
        lqw.orderByDesc(MonthlyOvertimeStat::getMonth);
        return lqw;
    }

    private void fillEmployeeInfoAndCalculateHours(MonthlyOvertimeStatVo vo) {
        employeeNameFiller.fillEmployeeName(vo,MonthlyOvertimeStatVo::getEmployeeNo,MonthlyOvertimeStatVo::setEmployeeName);
        // 计算小时数
        if (vo.getTotalMinutes() != null) {
            vo.setTotalOvertimeHours(vo.getTotalMinutes() / 60.0);
        }
        if (vo.getWorkdayMinutes() != null) {
            vo.setWeekdayOvertimeHours(vo.getWorkdayMinutes() / 60.0);
        }
        if (vo.getWeekendMinutes() != null) {
            vo.setWeekendOvertimeHours(vo.getWeekendMinutes() / 60.0);
        }
        if (vo.getHolidayMinutes() != null) {
            vo.setHolidayOvertimeHours(vo.getHolidayMinutes() / 60.0);
        }
    }

    @Override
    public MonthlyOvertimeStatVo queryById(Long statId) {
        MonthlyOvertimeStatVo vo = baseMapper.selectVoById(statId);
        if (vo != null) {
            fillEmployeeInfoAndCalculateHours(vo);
        }
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateMonthlyStats(Integer year, Integer month) {
        log.info("开始生成{}年{}月的月度加班统计", year, month);

        // 查询所有在职员工
        List<HrEmployee> employees = employeeMapper.selectList(
                Wrappers.lambdaQuery(HrEmployee.class)
                        .eq(HrEmployee::getEmployeeStatus, "1")); // 1-在职

        for (HrEmployee employee : employees) {
            try {
                regenerateEmployeeStats(employee.getEmployeeNo(), year, month);
            } catch (Exception e) {
                log.error("生成员工{}的月度加班统计失败", employee.getEmployeeNo(), e);
            }
        }

        log.info("月度加班统计生成完成,共处理{}个员工", employees.size());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void regenerateEmployeeStats(String employeeNo, Integer year, Integer month) {
        log.info("开始生成员工{}的{}年{}月加班统计", employeeNo, year, month);

        // 查询员工信息
        HrEmployee employee = employeeMapper.selectOne(
                Wrappers.lambdaQuery(HrEmployee.class)
                        .eq(HrEmployee::getEmployeeNo, employeeNo)
                        .last("LIMIT 1"));

        if (employee == null) {
            log.warn("员工不存在: {}", employeeNo);
            return;
        }

        // 计算月份的日期范围
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate startDate = yearMonth.atDay(1);
        LocalDate endDate = yearMonth.atEndOfMonth();

        // 删除已存在的统计记录
//        baseMapper.delete(Wrappers.lambdaQuery(MonthlyOvertimeStat.class)
//                .eq(MonthlyOvertimeStat::getEmployeeNo, employeeNo)
//                .eq(MonthlyOvertimeStat::getYear, year)
//                .eq(MonthlyOvertimeStat::getMonth, month));

        // 查询已通过的加班记录
        List<OvertimeRecord> records = overtimeRecordMapper.selectList(
                Wrappers.lambdaQuery(OvertimeRecord.class)
                        .eq(OvertimeRecord::getEmployeeNo, employeeNo)
                        .eq(OvertimeRecord::getApprovalStatus, "3") // 已通过
                        .between(OvertimeRecord::getOvertimeDate, startDate, endDate));

        if (records.isEmpty()) {
            log.info("员工{}在{}年{}月无加班记录", employeeNo, year, month);
            return;
        }

        // 统计数据
        MonthlyOvertimeStat stat = new MonthlyOvertimeStat();
        stat.setEmployeeNo(employeeNo);
        stat.setUserId(employee.getUserId());
        stat.setYear(year);
        stat.setMonth(month);

        int totalMinutes = 0;
        int workdayMinutes = 0;
        int weekendMinutes = 0;
        int holidayMinutes = 0;
        int overtimeCount = records.size();

        for (OvertimeRecord record : records) {
            Integer minutes = record.getOvertimeMinutes() != null ? record.getOvertimeMinutes() : 0;
            totalMinutes += minutes;

            // 按加班类型统计
            String overtimeType = record.getOvertimeType();
            if ("1".equals(overtimeType)) {
                workdayMinutes += minutes; // 工作日
            } else if ("2".equals(overtimeType)) {
                weekendMinutes += minutes; // 周末
            } else if ("3".equals(overtimeType)) {
                holidayMinutes += minutes; // 节假日
            }
        }

        stat.setTotalMinutes(totalMinutes);
        stat.setWorkdayMinutes(workdayMinutes);
        stat.setWeekendMinutes(weekendMinutes);
        stat.setHolidayMinutes(holidayMinutes);
        stat.setOvertimeCount(overtimeCount);
        stat.setStatus("0"); // 正常

        MonthlyOvertimeStat monthlyOvertimeStat = this.baseMapper.selectOne(new LambdaQueryWrapper<MonthlyOvertimeStat>()
            .eq(MonthlyOvertimeStat::getEmployeeNo, employeeNo)
            .eq(MonthlyOvertimeStat::getYear, year)
            .eq(MonthlyOvertimeStat::getMonth, month));

        if(Objects.nonNull(monthlyOvertimeStat)){
            stat.setStatId(monthlyOvertimeStat.getStatId());
            this.baseMapper.updateById(stat);
        }else {
            // 保存统计记录
            baseMapper.insert(stat);
        }
        log.info("员工{}的{}年{}月加班统计生成完成,总时长{}分钟", employeeNo, year, month, totalMinutes);
    }

    /**
     * 编辑
     * @param bo
     * @return
     */
    @Override
    public String edit(MonthlyOvertimeStatBo bo) {
        MonthlyOvertimeStat overtimeStat = MapstructUtils.convert(bo, MonthlyOvertimeStat.class);
        int i = this.baseMapper.updateById(overtimeStat);
        if(i > 0){
            return "编辑成功";
        }
        return "编辑失败";
    }
}
